﻿
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Sample.Common;
using Sample.Web.Controllers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace Sample.Web
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            Logger.SetLogWriter(new LogWriterFactory().Create());
            ExceptionPolicyFactory policyFactory = new ExceptionPolicyFactory();
            var exManager = policyFactory.CreateManager();

          

            ExceptionPolicy.SetExceptionManager(exManager);

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //Security points:
            //Not show MVC version in headers
            MvcHandler.DisableMvcResponseHeader = true;
        }
        protected void Application_Error(object sender, EventArgs e)
        {
            var httpContext = ((MvcApplication)sender).Context;

            var ex = Server.GetLastError();

            using (var controller = new HomeController())
            {
                DisplayException(httpContext, ex, controller);
            }

        }

        private static void DisplayException(HttpContext httpContext, Exception ex, Controller controller)
        {
            var httpContextBase = new HttpContextWrapper(httpContext);
            string errcontroller = RouteTable.Routes.GetRouteData(httpContextBase).Values["controller"].ToString();
            string erraction = RouteTable.Routes.GetRouteData(httpContextBase).Values["action"].ToString();
 
            var errorPath = httpContext.Request.Url.ToString();

            //Handle exception
            httpContext.ClearError();
            httpContext.Response.Clear();

            //if it is Ajax, its value will be overridden in HomeController.Error()
            httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : (int)HttpStatusCode.InternalServerError;
            httpContext.Response.TrySkipIisCustomErrors = true;

            Exception wrappedEx;
            try
            {
                ExceptionPolicy.HandleException(ex, ExceptionPolicyNames.UIPolicyName, out wrappedEx);
            }
            catch (Exception ee)
            {
                wrappedEx = ee;
                if (ExceptionPolicy.HandleException(ee, ExceptionPolicyNames.UIPolicyName))
                {
                    throw;
                }
            }

            if (ex is UnauthorizedAccessException)
            {
                var rd = new RouteData();
                rd.Values["controller"] = "Home";
                rd.Values["action"] = "Unauthorized";

                var requestContext = new RequestContext(httpContextBase, rd);
                controller.ViewBag.Url = httpContext.Request.Url.ToString();

                ((IController)controller).Execute(requestContext);
                return;
            }

            //Navigate to the error page
            var action = "Error";
            var routeData = new RouteData();
            routeData.Values["controller"] = "Home";
            routeData.Values["aspxerrorpath"] = errorPath;

            routeData.Values["exception"] = ex;
            var httpEx = ex as HttpException;


            if (httpEx == null)
            {
                //TODO: once release ,you can change the ex to wrappedEx
                controller.ViewData.Model = new HandleErrorInfo(ex, errcontroller, erraction);
            }
            else
            {
                switch (httpEx.GetHttpCode())
                {
                    case 404:
                        action = "NotFound";
                        break;
                    default:
                        controller.ViewData.Model = new HandleErrorInfo(ex, errcontroller, erraction);
                        break;
                        // others if any
                }
            }

            routeData.Values["action"] = action;

            ((IController)controller).Execute(new RequestContext(httpContextBase, routeData));
        }
    }
}
